package com.ddwl.funds.service;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.system.SystemUtil;
import com.alibaba.fastjson.JSON;
import com.ddwl.common.constant.BaseEnum;
import com.ddwl.common.constant.OrderTypeEnum;
import com.ddwl.common.constant.PaymentEnum;
import com.ddwl.common.exception.ParamException;
import com.ddwl.common.exception.PayException;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.common.util.UUIDGenerator;
import com.ddwl.funds.constant.FundsConstant;
import com.ddwl.funds.dao.*;
import com.ddwl.funds.dao.model.*;
import com.ddwl.schema.bo.funds.WxEntPayBo;
import com.ddwl.schema.util.DateUtil;
import com.ddwl.schema.vo.funds.WxEntPayVo;
import com.ddwl.schema.vo.funds.WxPaymentInfoVo;
import com.github.binarywang.wxpay.bean.entpay.*;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.EntPayService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.EntPayServiceImpl;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.github.binarywang.wxpay.util.SignUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 类WxPayServer.java的实现描述：微信支付处理
 *
 * @author zach
 * @Date :2020-06-02 18:11.
 */
@Slf4j
@Service
@RefreshScope
@RequiredArgsConstructor
public class WxPayServer {

    private final OrderWxPayDao orderWxPayDao;
    private final PaymentServer orderPayServer;
    private final WxPayConfigDao wxPayConfigDao;
    private final OrderWxPayRefundsDao orderWxPayRefundsDao;
    private final OrderPayDao orderPayDao;
    private final OrderRefundsDao orderRefundsDao;
    private final WxEntPayDao wxEntPayDao;
    private final RabbitTemplate rabbitTemplate;
    private Map<String, WxPayService> payServiceMap = new HashMap<>();

    @Value("${spring.profiles.active}")
    private String active;

    @Value("${ddwl.test.payamount}")
    private String testPayAmount;

    @Value("${ddwl.wxpay.notify_url}")
    private String payNotifyUrl;

    /**
     * 初始化微信支付信息
     */
    @PostConstruct
    public void init() {
        List<WxPaymentConfig> wxPaymentConfigs = wxPayConfigDao.selectAll();
        if (CollectionUtils.isEmpty(wxPaymentConfigs)) {
            return;
        }
        for (WxPaymentConfig wxPaymentConfig : wxPaymentConfigs) {
            WxPayService wxPayService = new WxPayServiceImpl();
            EntPayService entPayService = new EntPayServiceImpl(wxPayService);
            WxPayConfig payConfig = BeanConverUtils.convertBean(wxPaymentConfig, WxPayConfig.class);
            payConfig.setKeyPath(wxPaymentConfig.getCertPath());
            wxPayService.setConfig(payConfig);
            wxPayService.setEntPayService(entPayService);
            payServiceMap.put(wxPaymentConfig.getAppId(), wxPayService);
        }
    }


    /**
     * 创建微信支付订单
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NOT_SUPPORTED)
    public OrderWxPay createWxPayOrder(OrderPay orderPay) {
        //获取支付配置
        WxPaymentConfig wxPaymentConfig = null;
        if (orderPay.getPayAppId() != null) {
            wxPaymentConfig = wxPayConfigDao.getWxPayServerByAppId(orderPay.getPayAppId());
        } else if (wxPaymentConfig == null) {
            wxPaymentConfig = wxPayConfigDao.getWxPayServerByProduct(orderPay.getPayProduct());
        }
        OrderWxPay orderWxPay = orderWxPayDao.nowPay(orderPay.getOrderId(), wxPaymentConfig.getAppId());
        if (orderWxPay != null && orderWxPay.getExpirationTime().isAfter(Instant.now()) && DateUtil.addHours(orderWxPay.getGmtCreated(), 2).isAfter(Instant.now())) {
            return orderWxPay;
        }
        WxPayService wxPayService = getWxPayServer(wxPaymentConfig.getAppId());
        OrderWxPay wxPay = new OrderWxPay();
        wxPay.setId(UUIDGenerator.getShortUUID());
        wxPay.setOutTradeNo(orderPay.getOrderId());
        wxPay.setAppid(wxPayService.getConfig().getAppId());
        wxPay.setMchId(wxPayService.getConfig().getMchId());
        wxPay.setMchKey(wxPayService.getConfig().getMchKey());
        wxPay.setTotalFee((orderPay.getAmount().multiply(new BigDecimal(100))).intValue());
        wxPay.setBody(orderPay.getSubject());
        wxPay.setFeeType("CNY");
        wxPay.setTradeType(wxPayService.getConfig().getTradeType());
        wxPay.setNotifyUrl(StrUtil.format(payNotifyUrl, wxPay.getAppid()));
        wxPay.setProduct(orderPay.getProduct());
        wxPay.setOpenid(orderPay.getPayOpenId());
        wxPay.setStatus(BaseEnum.ApplyEnum.PRE.getCode());
        wxPay.setSpbillCreateIp(SystemUtil.getHostInfo().getAddress());
        wxPay.setExpirationTime(orderPay.getExpirationTime());
        wxPay.setNotifyUrl(wxPayService.getConfig().getNotifyUrl());
        WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder()
                .body(wxPay.getBody()).outTradeNo(wxPay.getId()).totalFee(wxPay.getTotalFee())
                .spbillCreateIp(wxPay.getSpbillCreateIp())
                .tradeType(wxPay.getTradeType()).notifyUrl(wxPay.getNotifyUrl())
                .timeExpire(DateUtil.formatDate(wxPay.getExpirationTime(), DateUtil.DATE_TIME_FORMAT1))
                .openid(wxPay.getOpenid())
                .build();
        if (FundsConstant.test_profile.contains(active) && !OrderTypeEnum.moreCredit.getCode().equals(orderPay.getOrderType())) {
            request.setTotalFee(new BigDecimal(testPayAmount).multiply(new BigDecimal(100)).intValue());
        }
        try {
            WxPayUnifiedOrderResult wxPayUnifiedOrderResult = wxPayService.unifiedOrder(request);
            wxPay.setPrepayId(wxPayUnifiedOrderResult.getPrepayId());
            orderWxPayDao.insert(wxPay);
        } catch (WxPayException e) {
            throw new PayException("微信创建订单异常", e);
        }
        return wxPay;
    }


    public WxPayService getWxPayServer(String appId) {
        if (!payServiceMap.containsKey(appId)) {
            WxPaymentConfig wxPaymentConfig = wxPayConfigDao.getWxPayServerByAppId(appId);
            if (wxPaymentConfig == null) {
                throw new PayException(StrUtil.format("未找到该appId={} 的支付配置信息", appId));
            }
            WxPayService wxPayService = new WxPayServiceImpl();
            EntPayService entPayService = new EntPayServiceImpl(wxPayService);
            WxPayConfig payConfig = BeanConverUtils.convertBean(wxPaymentConfig, WxPayConfig.class);
            payConfig.setKeyPath(wxPaymentConfig.getCertPath());
            wxPayService.setConfig(payConfig);
            wxPayService.setEntPayService(entPayService);
            payServiceMap.put(wxPaymentConfig.getAppId(), wxPayService);
            return wxPayService;
        }
        return payServiceMap.get(appId);
    }


    /**
     * 接受微信回调
     *
     * @param wxPayOrderNotifyResult
     */
    @Transactional(rollbackFor = Exception.class)
    public void wxPayNotify(WxPayOrderNotifyResult wxPayOrderNotifyResult) {
        //只处理成功的请求
        if (WxPayConstants.ResultCode.SUCCESS.equals(wxPayOrderNotifyResult.getResultCode())) {
            completePayment(wxPayOrderNotifyResult.getOutTradeNo(), wxPayOrderNotifyResult.getTransactionId());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void wxRefundNotify(WxPayRefundNotifyResult wxPayOrderNotifyResult) {
        //只处理成功的请求
        if (WxPayConstants.ResultCode.SUCCESS.equals(wxPayOrderNotifyResult.getReturnCode())) {
            WxPayRefundNotifyResult.ReqInfo reqInfo = wxPayOrderNotifyResult.getReqInfo();
            OrderWxPayRefunds orderWxPayRefunds = orderWxPayRefundsDao.getOutRefundNoByRefundId(reqInfo.getRefundId());
            ParamException.isNull(orderWxPayRefunds, "未找到微信退款单");
            ParamException.isTrue(BaseEnum.ApplyEnum.SUCCEED.getCode().equals(orderWxPayRefunds.getStatus()));
            OrderWxPayRefunds update = new OrderWxPayRefunds();
            update.setId(orderWxPayRefunds.getId());
            update.setStatus(BaseEnum.ApplyEnum.SUCCEED.getCode());
            update.setRefundAccount(reqInfo.getRefundAccount());
            update.setRefundRecvAccout(reqInfo.getRefundRecvAccout());
            orderWxPayRefundsDao.updateByPrimaryKeySelective(update);
            orderPayServer.completeRefunds(reqInfo.getOutRefundNo(), reqInfo.getTransactionId(), orderWxPayRefunds.getId());
        }
    }

    /**
     * 订单支付完成
     *
     * @param payId
     * @param transactionId
     */
    public void completePayment(String payId, String transactionId) {
        OrderWxPay orderWxPay = orderWxPayDao.selectByPrimaryKey(payId);
        ParamException.isNull(orderWxPay, "未找到微信支付单");
        if (!BaseEnum.ApplyEnum.SUCCEED.getCode().equals(orderWxPay.getStatus())) {
            OrderWxPay update = new OrderWxPay();
            update.setId(orderWxPay.getId());
            update.setTransactionId(transactionId);
            update.setStatus(BaseEnum.ApplyEnum.SUCCEED.getCode());
            orderWxPayDao.updateByPrimaryKeySelective(update);
        }
        orderPayServer.completePayment(orderWxPay.getAppid(), orderWxPay.getOutTradeNo(), transactionId, PaymentEnum.WX.getCode(), orderWxPay.getId());

    }


    /**
     * 返回调起微信小程序支付信息
     *
     * @return
     */
    public WxPaymentInfoVo getWxPayInfoVo(OrderWxPay orderWxPay) {
        WxPaymentInfoVo wxPayInfoVo = new WxPaymentInfoVo();
        wxPayInfoVo.setSignType(WxPayConstants.SignType.MD5);
        wxPayInfoVo.setTimeStamp(System.currentTimeMillis() / 1000 + "");
        wxPayInfoVo.setNonceStr(RandomUtil.randomString(10));
        wxPayInfoVo.setAppId(orderWxPay.getAppid());
        wxPayInfoVo.setPrepayId(orderWxPay.getPrepayId());
        wxPayInfoVo.setPartnerid(orderWxPay.getMchId());
        if (WxPayConstants.TradeType.APP.equals(orderWxPay.getTradeType())) {
            Map<String, String> params = new HashMap<>();
            params.put("appid",wxPayInfoVo.getAppId());
            params.put("partnerid",wxPayInfoVo.getPartnerid());
            params.put("prepayid",wxPayInfoVo.getPrepayId());
            params.put("package","Sign=WXPay");
            params.put("noncestr",wxPayInfoVo.getNonceStr());
            params.put("timestamp",wxPayInfoVo.getTimeStamp());
            wxPayInfoVo.setSign(SignUtils.createSign(params, orderWxPay.getMchKey()));
        } else if (WxPayConstants.TradeType.JSAPI.equals(orderWxPay.getTradeType())) {
            wxPayInfoVo.jsApiMd5Sign(orderWxPay.getMchKey());
        }
        return wxPayInfoVo;
    }


    /**
     * 主动查询微信当前订单的支付状态
     *
     * @param payId
     */
    public void queryWxPayStatus(String payId) {
        OrderWxPay orderWxPay = orderWxPayDao.nowPay(payId);
        //支付成功的直接返回
        if (BaseEnum.ApplyEnum.SUCCEED.getCode().equals(orderWxPay.getStatus())) {
            return;
        }
        WxPayOrderQueryResult queryResult = null;
        WxPayOrderQueryRequest request = WxPayOrderQueryRequest.newBuilder().outTradeNo(orderWxPay.getOutTradeNo()).build();
        try {
            queryResult = getWxPayServer(orderWxPay.getAppid()).queryOrder(request);
            log.info("微信订单查询返回,queryResult={}", JSON.toJSONString(queryResult));
        } catch (WxPayException e) {
            throw new PayException("查询微信订单异常", e);
        }
        if (WxPayConstants.ResultCode.SUCCESS.equals(queryResult.getResultCode())
                && WxPayConstants.ResultCode.SUCCESS.equals(queryResult.getTradeState())) {
            completePayment(queryResult.getOutTradeNo(), queryResult.getTransactionId());
        }
    }


    @Async
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NOT_SUPPORTED)
    public OrderWxPayRefunds refunds(OrderRefunds orderRefunds) {
        //获取支付配置
        WxPaymentConfig wxPaymentConfig = wxPayConfigDao.getWxPayServerByProduct(orderRefunds.getProduct());
        WxPayService wxPayService = getWxPayServer(wxPaymentConfig.getAppId());
        OrderWxPayRefunds wxPayRefunds = new OrderWxPayRefunds();
        WxPayConfig wxPayConfig = wxPayService.getConfig();
        wxPayRefunds.setAppId(wxPayConfig.getAppId());
        wxPayRefunds.setMchId(wxPayConfig.getMchId());
        wxPayRefunds.setOutTradeNo(orderRefunds.getOrderNo());
        wxPayRefunds.setProduct(orderRefunds.getProduct());
        wxPayRefunds.setOutRefundNo(orderRefunds.getId());
        wxPayRefunds.setRefundFee((orderRefunds.getRefundsAmount().multiply(new BigDecimal(100))).intValue());
        wxPayRefunds.setTotalFee((orderRefunds.getOrderAmount().multiply(new BigDecimal(100))).intValue());
        if (FundsConstant.test_profile.contains(active) && OrderTypeEnum.shopping.getCode().equals(orderRefunds.getOrderType())) {
            wxPayRefunds.setRefundFee(1);
            wxPayRefunds.setTotalFee(new BigDecimal(testPayAmount).multiply(new BigDecimal(100)).intValue());
        }
        wxPayRefunds.setStatus(BaseEnum.ApplyEnum.PRE.getCode());
        wxPayRefunds.setNotifyUrl(wxPaymentConfig.getRefundNotifyUrl());
        WxPayRefundRequest refundRequest = WxPayRefundRequest.newBuilder()
                //.outTradeNo(wxPayRefunds.getOutTradeNo())
                .transactionId(orderRefunds.getPayTradeNo())
                .outRefundNo(wxPayRefunds.getOutRefundNo())
                .totalFee(wxPayRefunds.getTotalFee())
                .refundFee(wxPayRefunds.getRefundFee())
                .notifyUrl(wxPayRefunds.getNotifyUrl())
                .build();
        try {
            WxPayRefundResult wxPayUnifiedOrderResult = wxPayService.refund(refundRequest);
            wxPayRefunds.setRefundId(wxPayUnifiedOrderResult.getRefundId());
            wxPayRefunds.setOutRefundNo(wxPayUnifiedOrderResult.getOutRefundNo());
            wxPayRefunds.setTransactionId(wxPayUnifiedOrderResult.getTransactionId());
            wxPayRefunds.setOutTradeNo(wxPayUnifiedOrderResult.getOutTradeNo());
            orderRefunds.setTransactionId(wxPayUnifiedOrderResult.getTransactionId());
            wxPayRefunds.setStatus(BaseEnum.ApplyEnum.PRE.getCode());
        } catch (WxPayException e) {
            wxPayRefunds.setStatus(BaseEnum.ApplyEnum.FILL.getCode());
            wxPayRefunds.setErrCode(e.getErrCode());
            wxPayRefunds.setErrCodeDes(e.getErrCodeDes());
            orderRefunds.setErrMsg(e.getErrCodeDes());
            orderRefunds.setRefundsFlowId(wxPayRefunds.getId());
            orderRefunds.setStatus(BaseEnum.ApplyEnum.FILL.getCode());
            throw new PayException("微信退款异常", e);
        } finally {
            orderRefundsDao.updateByPrimaryKeySelective(orderRefunds);
            if (StrUtil.isNotBlank(orderRefunds.getNotifyMethod())) {
                rabbitTemplate.convertAndSend(orderRefunds.getNotifyMethod(), JSON.toJSONString(orderRefunds));
            }
            orderWxPayRefundsDao.insert(wxPayRefunds);
        }
        return wxPayRefunds;
    }


    @Transactional(rollbackFor = Exception.class)
    public String dataCorrection() {
        String resp = "";
        List<OrderWxPay> orderWxPays = orderWxPayDao.queryOldPay();
        resp += "一共收到订正数据 " + orderWxPays.size() + "条,\t";
        List<String> orderIdList = new ArrayList<>();
        Integer add = 0;
        for (OrderWxPay orderWxPay : orderWxPays) {
            OrderPay orderPay = createOrderPay(orderWxPay);
            if (orderPay.getId() == null) {
                add += 1;
                orderPayDao.insert(orderPay);
                orderIdList.add(orderPay.getOrderId());
            }
        }
        resp += "订正数据 " + add + "条,\t过滤 " + (orderWxPays.size() - add) + "条";
        resp += "/n 订正订单ID如下:" + JSON.toJSONString(orderIdList);
        log.info(resp);
        return resp;
    }

    private OrderPay createOrderPay(OrderWxPay orderWxPay) {
        OrderPay orderPay = orderPayDao.getOrderPayByOrderId(orderWxPay.getOutTradeNo());
        if (orderPay == null) {
            orderPay = new OrderPay();
            orderPay.setPayType(PaymentEnum.WX.getCode());
            orderPay.setOrderType(OrderTypeEnum.shopping.getCode());
            orderPay.setPayAppId(orderWxPay.getAppid());
            orderPay.setTradeStatus(orderWxPay.getStatus());
            orderPay.setExpirationTime(orderWxPay.getExpirationTime());
            orderPay.setPayOpenId(orderWxPay.getOpenid());
            orderPay.setPayProduct(BaseEnum.ProductEnum.MALL.getName());
            orderPay.setOrderId(orderWxPay.getOutTradeNo());
            orderPay.setUserId("oldUser");
            orderPay.setReAmount(BigDecimal.ZERO);
            orderPay.setProduct(BaseEnum.ProductEnum.MALL.getName());
            orderPay.setSubject(orderWxPay.getBody());
            orderPay.setTradeNo(orderWxPay.getTransactionId());
            orderPay.setPayTimes(1);
            orderPay.setAmount(new BigDecimal(orderWxPay.getTotalFee()).divide(new BigDecimal("100")));
            orderPay.setPayMchId(orderWxPay.getMchId());
            orderPay.setNotifyMethod("order.pay.notify.queue");
        }
        return orderPay;
    }


    public void queryRefunds(OrderRefunds orderRefunds) {
        OrderWxPayRefunds wxPayRefunds = orderWxPayRefundsDao.selectByPrimaryKey(orderRefunds.getRefundsFlowId());
        if (wxPayRefunds == null) {
            refunds(orderRefunds);
            return;
        }
        if (BaseEnum.ApplyEnum.SUCCEED.getCode().equals(wxPayRefunds.getStatus())) {
            orderRefunds.setStatus(BaseEnum.ApplyEnum.SUCCEED.getCode());
            orderRefunds.setTransactionId(wxPayRefunds.getTransactionId());
            orderRefunds.setRefundsFlowId(wxPayRefunds.getId());
            orderRefundsDao.updateByPrimaryKeySelective(orderRefunds);
            if (StrUtil.isNotBlank(orderRefunds.getNotifyMethod())) {
                rabbitTemplate.convertAndSend(orderRefunds.getNotifyMethod(), JSON.toJSONString(orderRefunds));
            }
        } else {
            try {
                WxPayRefundQueryResult wxPayRefundQueryResult = getWxPayServer(wxPayRefunds.getAppId()).refundQuery(null, null, null, wxPayRefunds.getRefundId());
                log.info("微信退款查询返回 wxPayRefundQueryResult={}", JSON.toJSONString(wxPayRefundQueryResult));
                orderRefunds.setStatus(BaseEnum.ApplyEnum.SUCCEED.getCode());
                wxPayRefunds.setStatus(BaseEnum.ApplyEnum.SUCCEED.getCode());
            } catch (WxPayException e) {
                wxPayRefunds.setStatus(BaseEnum.ApplyEnum.FILL.getCode());
                wxPayRefunds.setErrCode(e.getErrCode());
                wxPayRefunds.setErrCodeDes(e.getErrCodeDes());
                orderRefunds.setErrMsg(e.getErrCodeDes());
                orderRefunds.setRefundsFlowId(wxPayRefunds.getId());
                orderRefunds.setStatus(BaseEnum.ApplyEnum.FILL.getCode());
                log.error("查询微信退款异常", e);
            } finally {
                orderRefundsDao.updateByPrimaryKeySelective(orderRefunds);
                if (StrUtil.isNotBlank(orderRefunds.getNotifyMethod())) {
                    rabbitTemplate.convertAndSend(orderRefunds.getNotifyMethod(), JSON.toJSONString(orderRefunds));
                }
                orderWxPayRefundsDao.updateByPrimaryKeySelective(wxPayRefunds);
            }
        }
    }

    public void entPay(WxEntPayBo bo) {
        if (FundsConstant.WxEntPayType.WX_WALLET.getCode().equals(bo.getPayType())) {
            entPayWallet(bo);
        }
        if (FundsConstant.WxEntPayType.BANK_CARD.getCode().equals(bo.getPayType())) {
            entPayBank(bo);
        }
    }

    private void entPayWallet(WxEntPayBo bo) {
        WxPaymentConfig wxPaymentConfig = wxPayConfigDao.getWxPayServerByAppId(bo.getMchAppid());
        WxPayService wxPayService = getWxPayServer(wxPaymentConfig.getAppId());
        EntPayRequest request = EntPayRequest.newBuilder()
                .mchAppid(wxPaymentConfig.getAppId()).mchId(wxPaymentConfig.getMchId()).openid(bo.getOpenid()).partnerTradeNo(bo.getPartnerTradeNo())
                .checkName(WxPayConstants.CheckNameOption.FORCE_CHECK).reUserName(bo.getReUserName()).amount(bo.getAmount()).description(bo.getDesc())
                .spbillCreateIp(SystemUtil.getHostInfo().getAddress()).build();

        WxEntPay wxEntPay = BeanConverUtils.convertBean(request, WxEntPay.class);
        wxEntPay.setPayType(bo.getPayType());
        wxEntPay.setNonceStr(request.getNonceStr());
        wxEntPay.setSign(request.getSign());
        wxEntPay.setDescription(request.getDescription());
        wxEntPay.setNotifyQueue(bo.getNotifyQueue());

        WxEntPayVo vo = new WxEntPayVo();
        vo.setPartnerTradeNo(bo.getPartnerTradeNo());

        if (FundsConstant.test_profile.contains(active)) {
            vo.setStatus(FundsConstant.WxEntPayStatus.SUCCESS.name());
        } else {
            try {
                EntPayResult entPayResult = doPayWallet(wxPayService, request);
                log.info("entPayWallet result: [{}]", JSON.toJSONString(entPayResult));
                wxEntPay.setReturnCode(entPayResult.getReturnCode());
                wxEntPay.setReturnMsg(entPayResult.getReturnMsg());
                wxEntPay.setResultCode(entPayResult.getResultCode());
                wxEntPay.setPaymentNo(entPayResult.getPaymentNo());
                wxEntPay.setPaymentTime(entPayResult.getPaymentTime());
                vo.setStatus(FundsConstant.WxEntPayStatus.SUCCESS.name());
                vo.setPaymentNo(entPayResult.getPaymentNo());
            } catch (WxPayException e) {
                log.error("企业微信付款到零钱出错：", e);
                wxEntPay.setReturnCode(e.getReturnCode());
                wxEntPay.setReturnMsg(e.getReturnMsg());
                wxEntPay.setResultCode(e.getResultCode());
                wxEntPay.setErrCode(e.getErrCode());
                wxEntPay.setErrCodeDes(e.getErrCodeDes());
                vo.setStatus(FundsConstant.WxEntPayStatus.FAILED.name());
                vo.setReason(e.getErrCodeDes());
            }
        }
        if (StringUtils.hasText(bo.getNotifyQueue())) {
            rabbitTemplate.convertAndSend(bo.getNotifyQueue(), JSON.toJSONString(vo));
        }
        wxEntPayDao.insert(wxEntPay);
    }

    private EntPayResult doPayWallet(WxPayService wxPayService, EntPayRequest request) throws WxPayException {
        EntPayResult entPayResult = null;
        try {
            entPayResult = wxPayService.getEntPayService().entPay(request);
        } catch (WxPayException e) {
            try {
                entPayResult = wxPayService.getEntPayService().entPay(request);
            } catch (WxPayException wxPayException) {
                throw wxPayException;
            }
        }
        return entPayResult;
    }

    private void entPayBank(WxEntPayBo bo) {
        WxPaymentConfig wxPaymentConfig = wxPayConfigDao.getWxPayServerByAppId(bo.getMchAppid());
        WxPayService wxPayService = getWxPayServer(wxPaymentConfig.getAppId());
        EntPayBankRequest request = EntPayBankRequest.builder()
                .partnerTradeNo(UUIDGenerator.getTimeUUID()).encBankNo(bo.getEncBankNo())
                .encTrueName(bo.getEncTrueName()).bankCode(bo.getBankCode()).amount(bo.getAmount()).description(bo.getDesc()).build();

        WxEntPay wxEntPay = BeanConverUtils.convertBean(request, WxEntPay.class);
        wxEntPay.setMchAppid(request.getAppid());
        wxEntPay.setMchId(request.getMchId());
        wxEntPay.setNonceStr(request.getNonceStr());
        wxEntPay.setSign(request.getSign());
        wxEntPay.setDescription(request.getDescription());
        wxEntPay.setPayType(bo.getPayType());
        wxEntPay.setNotifyQueue(bo.getNotifyQueue());

        WxEntPayVo vo = new WxEntPayVo();
        vo.setPartnerTradeNo(bo.getPartnerTradeNo());

        if (FundsConstant.test_profile.contains(active)) {
            vo.setStatus(FundsConstant.WxEntPayStatus.SUCCESS.name());
        } else {
            try {
                EntPayBankResult entPayBankResult = doPayBank(wxPayService, request);
                log.info("entPayBank result: [{}]", JSON.toJSONString(entPayBankResult));
                wxEntPay.setReturnCode(entPayBankResult.getReturnCode());
                wxEntPay.setReturnMsg(entPayBankResult.getReturnMsg());
                wxEntPay.setResultCode(entPayBankResult.getResultCode());
                wxEntPay.setPaymentNo(entPayBankResult.getPaymentNo());
                wxEntPay.setCmmsAmt(entPayBankResult.getCmmsAmount());
                vo.setStatus(FundsConstant.WxEntPayStatus.SUCCESS.name());
                vo.setPaymentNo(entPayBankResult.getPaymentNo());
            } catch (WxPayException e) {
                log.error("企业微信付款到银行卡出错：", e);
                wxEntPay.setReturnCode(e.getReturnCode());
                wxEntPay.setReturnMsg(e.getReturnMsg());
                wxEntPay.setResultCode(e.getResultCode());
                wxEntPay.setErrCode(e.getErrCode());
                wxEntPay.setErrCodeDes(e.getErrCodeDes());
                vo.setStatus(FundsConstant.WxEntPayStatus.FAILED.name());
                vo.setReason(e.getErrCodeDes());
            }
        }
        if (StringUtils.hasText(bo.getNotifyQueue())) {
            rabbitTemplate.convertAndSend(bo.getNotifyQueue(), JSON.toJSONString(vo));
        }
        wxEntPayDao.insert(wxEntPay);
    }

    private EntPayBankResult doPayBank(WxPayService wxPayService, EntPayBankRequest request) throws WxPayException {
        EntPayBankResult entPayBankResult = null;
        try {
            entPayBankResult = wxPayService.getEntPayService().payBank(request);
        } catch (WxPayException e) {
            try {
                entPayBankResult = wxPayService.getEntPayService().payBank(request);
            } catch (WxPayException wxPayException) {
                throw wxPayException;
            }
        }
        return entPayBankResult;
    }

    public void queryEntPayWallet(String appId, String partnerTradeNo) {
        WxEntPay entity = wxEntPayDao.selectByPartnerTradeNo(partnerTradeNo);
        ParamException.isNull(entity);
        WxPaymentConfig wxPaymentConfig = wxPayConfigDao.getWxPayServerByAppId(appId);
        WxPayService wxPayService = getWxPayServer(wxPaymentConfig.getAppId());

        WxEntPay wxEntPay = new WxEntPay();
        wxEntPay.setId(entity.getId());

        WxEntPayVo vo = new WxEntPayVo();
        vo.setPartnerTradeNo(partnerTradeNo);

        if (FundsConstant.test_profile.contains(active)) {
            vo.setStatus(FundsConstant.WxEntPayStatus.SUCCESS.name());
        } else {
            try {
                EntPayQueryResult entPayQueryResult = wxPayService.getEntPayService().queryEntPay(partnerTradeNo);
                log.info("queryEntPayWallet result: [{}]", JSON.toJSONString(entPayQueryResult));
                wxEntPay.setReturnCode(entPayQueryResult.getReturnCode());
                wxEntPay.setReturnMsg(entPayQueryResult.getReturnMsg());
                wxEntPay.setResultCode(entPayQueryResult.getResultCode());
                wxEntPay.setStatus(entPayQueryResult.getStatus());
                wxEntPay.setReason(entPayQueryResult.getReason());
                wxEntPay.setPaymentTime(entPayQueryResult.getPaymentTime());
                vo.setStatus(entPayQueryResult.getStatus());
                vo.setPaymentNo(entPayQueryResult.getDetailId());
                vo.setReason(entPayQueryResult.getReason());
            } catch (WxPayException e) {
                log.error("查询微信付款到零钱出错：", e);
                wxEntPay.setReturnCode(e.getReturnCode());
                wxEntPay.setReturnMsg(e.getReturnMsg());
                wxEntPay.setResultCode(e.getResultCode());
                wxEntPay.setErrCode(e.getErrCode());
                wxEntPay.setErrCodeDes(e.getErrCodeDes());
                vo.setStatus(FundsConstant.WxEntPayStatus.FAILED.name());
                vo.setReason(e.getErrCodeDes());
            }
        }
        rabbitTemplate.convertAndSend(entity.getNotifyQueue(), JSON.toJSONString(vo));
        wxEntPayDao.updateByPrimaryKeySelective(wxEntPay);
    }

    public void queryPayBank(String appId, String partnerTradeNo) {
        WxEntPay entity = wxEntPayDao.selectByPartnerTradeNo(partnerTradeNo);
        ParamException.isNull(entity);
        WxPaymentConfig wxPaymentConfig = wxPayConfigDao.getWxPayServerByAppId(appId);
        WxPayService wxPayService = getWxPayServer(wxPaymentConfig.getAppId());

        WxEntPay wxEntPay = new WxEntPay();
        wxEntPay.setId(entity.getId());

        WxEntPayVo vo = new WxEntPayVo();
        vo.setPartnerTradeNo(partnerTradeNo);

        if (FundsConstant.test_profile.contains(active)) {
            vo.setStatus(FundsConstant.WxEntPayStatus.SUCCESS.name());
        } else {
            try {
                EntPayBankQueryResult entPayBankQueryResult = wxPayService.getEntPayService().queryPayBank(partnerTradeNo);
                log.info("queryPayBank result: [{}]", JSON.toJSONString(entPayBankQueryResult));
                wxEntPay.setReturnCode(entPayBankQueryResult.getReturnCode());
                wxEntPay.setReturnMsg(entPayBankQueryResult.getReturnMsg());
                wxEntPay.setResultCode(entPayBankQueryResult.getResultCode());
                wxEntPay.setStatus(entPayBankQueryResult.getStatus());
                wxEntPay.setReason(entPayBankQueryResult.getFailReason());
                vo.setStatus(entPayBankQueryResult.getStatus());
            } catch (WxPayException e) {
                log.error("查询微信付款到银行卡出错：", e);
                wxEntPay.setReturnCode(e.getReturnCode());
                wxEntPay.setReturnMsg(e.getReturnMsg());
                wxEntPay.setResultCode(e.getResultCode());
                wxEntPay.setErrCode(e.getErrCode());
                wxEntPay.setErrCodeDes(e.getErrCodeDes());
                vo.setStatus(FundsConstant.WxEntPayStatus.FAILED.name());
            }
        }
        rabbitTemplate.convertAndSend(entity.getNotifyQueue(), JSON.toJSONString(vo));
        wxEntPayDao.updateByPrimaryKeySelective(wxEntPay);
    }


}